﻿using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ServiceRegisterDiscoveryExtensions
{
    public static class ConsulExtensions
    {
        #region 服务注册
        /// <summary>
        /// 服务注册到Consul
        /// </summary>
        /// <param name="services"></param>
        /// <param name="registration"></param>
        /// <returns></returns>
        public static IServiceCollection AddConsulRegister(this IServiceCollection services, AgentServiceRegistration registration)
        {
            // 检查数据
            CheckConfig(registration);
            return services.AddSingleton<AgentServiceRegistration>(registration);
        }

        /// <summary>
        /// 启用consul注册
        /// </summary>
        /// <param name="app"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static IApplicationBuilder UseConsulRegister(this IApplicationBuilder app)
        {
            // 获取Consul注册信息
            AgentServiceRegistration registration = app.ApplicationServices.GetRequiredService<AgentServiceRegistration>();
            bool consulHostExist = registration.Meta.TryGetValue("ConsulHost", out string consulHost);
            ConsulClient consulClient = new ConsulClient(conf =>
            {
                conf.Address = new Uri(consulHost); //服务注册地址：集群中任意一个地址
            });

            // 获取主机生命周期对象
            IHostApplicationLifetime lifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();
            // 服务启动后,向consul注册
            lifetime.ApplicationStarted.Register(async () =>
            {
                WriteResult writeResult = await consulClient.Agent.ServiceRegister(registration); // 注册到consul
            });
            // 程序停止时,向consul注销
            lifetime.ApplicationStopping.Register(async () =>
            {
                WriteResult writeResult = await consulClient.Agent.ServiceDeregister(registration.ID);
            });

            return app;
        }

        /// <summary>
        /// 检查配置文件
        /// </summary>
        /// <param name="serviceOptions"></param>
        private static void CheckConfig(AgentServiceRegistration registration)
        {
            if (string.IsNullOrEmpty(registration?.Address))
                throw new Exception("请正确配置Address");

            if (registration.Meta.TryGetValue("ConsulHost", out string consulHost) == false)
                throw new Exception("请在ConsulRegistrationMessage->Meta,添加ConsulHost属性");

            if (string.IsNullOrEmpty(registration.Check?.HTTP))
                throw new Exception("请在ConsulRegistrationMessage->Check->HTTP配置健康检查接口");

        }

        #endregion

        #region 服务发现
        public static IServiceCollection AddConsulDiscovery(this IServiceCollection services, string consulAddress, string datacenter = "dc1")
        {
            ConsulClient client = new ConsulClient(conf =>
            {
                conf.Address = new Uri(consulAddress);
                conf.Datacenter = datacenter;
            });
            return services.AddSingleton(client);
        }

        #endregion

    }
}